package com.fwtai.service.web;

import com.alibaba.fastjson2.JSONObject;
import com.fwtai.api.ApiBuyDao;
import com.fwtai.bean.PageFormData;
import com.fwtai.bean.UploadFile;
import com.fwtai.bean.UploadObject;
import com.fwtai.service.AsyncService;
import com.fwtai.tool.IdBuilder;
import com.fwtai.tool.ToolClient;
import com.fwtai.tool.ToolString;
import com.fwtai.web.PartnerDao;
import com.fwtai.web.StoreDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 门店业务层
 * @作者 李宇鹏
 * @版本 v1.0
 * @QQ号码 444141300
 * @创建日期 2023-03-13 16:30:23
 * @官网 <url>http://www.fwtai.com</url>
*/
@Service
public class StoreService{

  @Value("${upload_dir_window}")
  private String dir_window;

  @Value("${upload_dir_linux}")
  private String dir_linux;

  private final AsyncService asyncService;

  private final StoreDao storeDao;

  private final PartnerDao partnerDao;

  private final ThreadPoolTaskExecutor taskExecutor;

  private final ApiBuyDao apiBuyDao;

  public StoreService(final StoreDao storeDao,final ThreadPoolTaskExecutor taskExecutor,final ApiBuyDao apiBuyDao,final AsyncService asyncService,final PartnerDao partnerDao){
    this.storeDao = storeDao;
    this.taskExecutor = taskExecutor;
    this.asyncService = asyncService;
    this.partnerDao = partnerDao;
    this.apiBuyDao = apiBuyDao;
  }

  public String add(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_name = "name";
      final String p_thumbnail = "thumbnail";
      final String p_pictures = "pictures";
      final String p_contacts = "contacts";
      final String p_telephone = "telephone";
      final String p_longitude = "longitude";
      final String p_latitude = "latitude";
      final String p_time_frame = "time_frame";
      final String p_province_id = "province_id";
      final String p_province_name = "province_name";
      final String p_city_id = "city_id";
      final String p_city_name = "city_name";
      final String p_county_id = "county_id";
      final String p_county_name = "county_name";
      final String p_address = "address";
      final String p_introduce = "introduce";
      final String validate = ToolClient.validateField(formData,p_name,p_province_id,p_province_name,p_city_id,p_city_name,p_county_id,p_county_name,p_address);
      if(validate != null) return validate;
      final String len_name = formData.getString(p_name);
      if(len_name != null && len_name.length() > 128){
        return ToolClient.createJsonFail("门店名称字数太多");
      }
      final String len_contacts = formData.getString(p_contacts);
      if(len_contacts != null && len_contacts.length() > 40){
        return ToolClient.createJsonFail("门店联系人字数太多");
      }
      final String len_telephone = formData.getString(p_telephone);
      if(len_telephone != null && len_telephone.length() > 20){
        return ToolClient.createJsonFail("门店联系电话字数太多");
      }
      final String len_longitude = formData.getString(p_longitude);
      if(len_longitude != null && len_longitude.length() > 40){
        return ToolClient.createJsonFail("门店的经度字数太多");
      }
      final String len_latitude = formData.getString(p_latitude);
      if(len_latitude != null && len_latitude.length() > 40){
        return ToolClient.createJsonFail("门店的纬度字数太多");
      }
      final String len_time_frame = formData.getString(p_time_frame);
      if(len_time_frame != null && len_time_frame.length() > 20){
        return ToolClient.createJsonFail("营业时间（格式：09:00-22:00）字数太多");
      }
      final String len_province_id = formData.getString(p_province_id);
      if(len_province_id != null && len_province_id.length() > 20){
        return ToolClient.createJsonFail("省主键kid字数太多");
      }
      final String len_province_name = formData.getString(p_province_name);
      if(len_province_name != null && len_province_name.length() > 40){
        return ToolClient.createJsonFail("省名称字数太多");
      }
      final String len_city_id = formData.getString(p_city_id);
      if(len_city_id != null && len_city_id.length() > 20){
        return ToolClient.createJsonFail("市主键kid字数太多");
      }
      final String len_city_name = formData.getString(p_city_name);
      if(len_city_name != null && len_city_name.length() > 20){
        return ToolClient.createJsonFail("市名称字数太多");
      }
      final String len_county_id = formData.getString(p_county_id);
      if(len_county_id != null && len_county_id.length() > 20){
        return ToolClient.createJsonFail("区县kid字数太多");
      }
      final String len_county_name = formData.getString(p_county_name);
      if(len_county_name != null && len_county_name.length() > 20){
        return ToolClient.createJsonFail("区县名称字数太多");
      }
      final String len_address = formData.getString(p_address);
      if(len_address != null && len_address.length() > 128){
        return ToolClient.createJsonFail("地址字数太多");
      }
      final String len_introduce = formData.getString(p_introduce);
      if(len_introduce != null && len_introduce.length() > 921600000){
        return ToolClient.createJsonFail("门店介绍字数太多");
      }
      final Long v_province_id = formData.getLong(p_province_id);
      if(v_province_id == null){
        return ToolClient.createJsonFail("省主键kid不是有效的数据格式");
      }else{
        formData.put(p_province_id,v_province_id);
      }
      final Long v_city_id = formData.getLong(p_city_id);
      if(v_city_id == null){
        return ToolClient.createJsonFail("市主键kid不是有效的数据格式");
      }else{
        formData.put(p_city_id,v_city_id);
      }
      final Long v_county_id = formData.getLong(p_county_id);
      if(v_county_id == null){
        return ToolClient.createJsonFail("区县kid不是有效的数据格式");
      }else{
        formData.put(p_county_id,v_county_id);
      }
      final String baseDir = ToolString.isLinuxOS() ? dir_linux : dir_window;
      final UploadObject uploadObject = ToolClient.uploadFile(request,baseDir,"/store",false,6,20,false);
      final String errorMsg = uploadObject.getErrorMsg();
      if(errorMsg != null) return ToolClient.createJsonFail(errorMsg);
      final ArrayList<UploadFile> listFiles = uploadObject.getListFiles();
      formData.remove(p_thumbnail);
      formData.remove(p_pictures);
      final boolean b = listFiles == null || listFiles.isEmpty();
      if(!b){
        final ArrayList<String> lists = new ArrayList<>(1);
        lists.add(p_thumbnail);
        handlerFile(formData,listFiles,lists);//适用于json类型且是单文件字段
        final ArrayList<String> listName = new ArrayList<>(1);
        listFiles.forEach(uploadFile -> {
          listName.add(uploadFile.getName());
        });
        //list分组
        final Map<String,List<String>> collects = listName.stream().collect(Collectors.groupingBy(itemValue -> {
          return itemValue.substring(0,itemValue.length() - 1);
        }));
        asyncService.handlerFile(formData,listFiles,collects,p_pictures);//多文件上传,若有bug则换用下面注释的那个
        final String[] listMulti = new String[]{p_pictures};//多文件上传的字段集
        handlerFile(formData,listFiles,collects,listMulti);//多文件上传
      }
      formData.put("kid",new IdBuilder().getId121L());
      return ToolClient.executeRows(storeDao.add(formData));
    },taskExecutor).join();
  }

  public String edit(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_kid = "kid";
      final String p_name = "name";
      final String p_thumbnail = "thumbnail";
      final String p_pictures = "pictures";
      final String p_contacts = "contacts";
      final String p_telephone = "telephone";
      final String p_longitude = "longitude";
      final String p_latitude = "latitude";
      final String p_time_frame = "time_frame";
      final String p_address = "address";
      final String p_introduce = "introduce";
      final String validate = ToolClient.validateField(formData,p_kid,p_name,p_address);
      if(validate != null) return validate;
      final String len_name = formData.getString(p_name);
      if(len_name != null && len_name.length() > 128){
        return ToolClient.createJsonFail("门店名称字数太多");
      }
      final String len_contacts = formData.getString(p_contacts);
      if(len_contacts != null && len_contacts.length() > 40){
        return ToolClient.createJsonFail("门店联系人字数太多");
      }
      final String len_telephone = formData.getString(p_telephone);
      if(len_telephone != null && len_telephone.length() > 20){
        return ToolClient.createJsonFail("门店联系电话字数太多");
      }
      final String len_longitude = formData.getString(p_longitude);
      if(len_longitude != null && len_longitude.length() > 40){
        return ToolClient.createJsonFail("门店的经度字数太多");
      }
      final String len_latitude = formData.getString(p_latitude);
      if(len_latitude != null && len_latitude.length() > 40){
        return ToolClient.createJsonFail("门店的纬度字数太多");
      }
      final String len_time_frame = formData.getString(p_time_frame);
      if(len_time_frame != null && len_time_frame.length() > 20){
        return ToolClient.createJsonFail("营业时间（格式：09:00-22:00）字数太多");
      }
      final String len_address = formData.getString(p_address);
      if(len_address != null && len_address.length() > 128){
        return ToolClient.createJsonFail("地址字数太多");
      }
      final String len_introduce = formData.getString(p_introduce);
      if(len_introduce != null && len_introduce.length() > 921600000){
        return ToolClient.createJsonFail("门店介绍字数太多");
      }
      final HashMap<String,String> v = storeDao.queryExistById(formData.getLong(p_kid));
      if(v == null){
        return ToolClient.createJsonFail("数据不存在,刷新重试");
      }
      final String baseDir = ToolString.isLinuxOS() ? dir_linux : dir_window;
      final UploadObject uploadObject = ToolClient.uploadFile(request,baseDir,"/store",false,6,20,false);
      final String errorMsg = uploadObject.getErrorMsg();
      if(errorMsg != null) return ToolClient.createJsonFail(errorMsg);
      final ArrayList<UploadFile> listFiles = uploadObject.getListFiles();
      final boolean b = listFiles != null && !listFiles.isEmpty();
      formData.remove(p_thumbnail);
      formData.remove(p_pictures);
      final String[] listMulti = new String[]{p_pictures};//多文件上传的字段集
      if(b){
        final ArrayList<String> lists = new ArrayList<>(1);
        lists.add(p_thumbnail);
        handlerFile(formData,listFiles,lists);//适用于json类型(单文件上传)
        final ArrayList<String> listName = new ArrayList<>(2);
        listFiles.forEach(uploadFile -> listName.add(uploadFile.getName()));
        //list分组,会含单文件字段,但不影响下列的操作
        final Map<String,List<String>> collects = listName.stream().collect(Collectors.groupingBy(itemValue -> itemValue.substring(0,itemValue.length() - 1)));
        asyncService.handlerFile(formData,listFiles,collects,listMulti);//适用于json类型(多文件上传)
        formData.put("collects_columns",collects);//获取已上传文件的字段
      }
      formData.put(p_kid,formData.getLong(p_kid));
      final int rows = storeDao.edit(formData);
      if(rows > 0 && b){
        final Map<String,List<String>> columns = (Map<String,List<String>>) formData.get("collects_columns");
        if(columns != null){
          final HashMap<String,List<String>> mapRemove = new HashMap<>(listFiles.size());//收集多文件字段
          for(final String key : columns.keySet()){
            for(int x = listMulti.length - 1; x >= 0; x--){
              final String val = listMulti[x];
              if(key.equals(val)){
                asyncService.delFileJsonObjects(v.get(key));//多文件上传,json里含json
                mapRemove.put(key,columns.get(key));
                break;
              }
            }
          }
          for(final String key : mapRemove.keySet()){
            final List<String> listRemove = mapRemove.get(key);
            for(int x = listRemove.size() - 1; x >= 0; x--){
              final String name = listRemove.get(x);
              for (int i = 0; i < listFiles.size(); i++){
                final String fileName = listFiles.get(i).getName();
                if(name.equals(fileName)){
                  listFiles.remove(i);//移除多文件字段的key
                  i = i - 1;
                  break;
                }
              }
            }
          }
          for(int y = listFiles.size() - 1; y >= 0; y--){
            final UploadFile uploadFile = listFiles.get(y);
            final String fileName = uploadFile.getName();
            for(final String key : v.keySet()){
              if(key.equals(fileName)){
                asyncService.delFileJsonObject(v.get(key));//删除单文件字段的文件
                break;
              }
            }
          }
        }
      }
      return ToolClient.executeRows(rows);
    },taskExecutor).join();
  }

  public String editAuth(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_kid = "kid";
      final String p_state = "state";
      final String p_user_id = "user_id";
      final String validate = ToolClient.validateField(formData,p_kid,p_state,p_user_id);
      if(validate != null) return validate;
      final Long userId = formData.getLong(p_user_id);
      final Integer state = formData.getInteger(p_state);
      if(state == 2){
        //查询是否有上级
        final String referrer = partnerDao.getParentReferrer(userId);
        if(referrer != null && referrer.length() == 0){
          return ToolClient.createJsonFail("审核失败,当前申请人已被其他成功邀请");
        }
        final List<Integer> self = partnerDao.getProxySelf(userId);
        if(self != null && self.size() > 0){
          return ToolClient.createJsonFail("审核失败,当前账号已成功申请门店或其他代理");
        }
        //绑定上下级关系,申请人绑定给推荐
        final Long storeId = formData.getLong(p_kid);
        final String code = partnerDao.getStoreCode(storeId);//获取邀请码,是否可能为空？
        if(code != null){
          formData.put("invitation_code",code);
          formData.put("relationUserId",userId);
          return ToolClient.executeRows(storeDao.editAuthCode(formData));
        }
        return ToolClient.executeRows(storeDao.editAuth2(formData));
      }
      return ToolClient.executeRows(storeDao.editAuth(formData));
    },taskExecutor).join();
  }

  //适用于添加或编辑的单文件上传
  public void handlerFile(final PageFormData formData,final ArrayList<UploadFile> listFiles,final ArrayList<String> lists){
    listFiles.forEach(uploadFile -> {
      final JSONObject json = new JSONObject(3);
      json.put("fullPath",uploadFile.getFullPath());
      json.put("urlFile",uploadFile.getUrlFile());
      json.put("fileSize",uploadFile.getFileSize());
      json.put("originalName",uploadFile.getOriginalName());
      final String name = uploadFile.getName();
      for(int i = lists.size() - 1; i >= 0; i--){
        final String value = lists.get(i);
        if(name.equals(value)){
          formData.put(name,json.toJSONString());
          break;
        }
      }
    });
  }

  //多文件上传,json里含json
  private void handlerFile(final PageFormData formData,final ArrayList<UploadFile> listFiles,final Map<String,List<String>> maps,final String... keys){
    for(int x = keys.length - 1; x >= 0; x--){
      final String fieldKey = keys[x];//数据库表的字段
      final List<String> lists = maps.get(fieldKey);
      if(lists != null){
        final JSONObject result = new JSONObject(lists.size()+2);
        for(int y = lists.size() - 1; y >= 0; y--){
          final String value = lists.get(y);
          for(int z = listFiles.size() - 1; z >= 0; z--){
            final UploadFile uploadFile = listFiles.get(z);
            final String name = uploadFile.getName();
            if(name.equals(value)){
              final JSONObject object = new JSONObject(4);
              object.put("fullPath",uploadFile.getFullPath());
              object.put("urlFile",uploadFile.getUrlFile());
              object.put("fileSize",uploadFile.getFileSize());
              object.put("originalName",uploadFile.getOriginalName());
              result.put(name,object);
              if(y==0){
                result.put("total",lists.size());
                result.put("fieldKey",fieldKey);
              }
              break;
            }
          }
        }
        formData.put(fieldKey,result.toString());
      }
    }
  }

  public String queryById(final Long kid){
    return CompletableFuture.supplyAsync(()->{
      if(kid == null){
        return ToolClient.jsonValidateField();
      }
      return ToolClient.queryJson(storeDao.queryById(kid));
    },taskExecutor).join();
  }

  //编辑时的文件删除可参考此方法
  public String delById(final Long kid){
    //若用到ThreadLocal的数据可在此组装
    return CompletableFuture.supplyAsync(()->{
      if(kid == null){
        return ToolClient.jsonValidateField();
      }
      final HashMap<String,String> map = storeDao.queryExistById(kid);
      if(map == null){// 此处map == null永远为true，所以map.isEmpty()永远为true，要非空时 if(map != null){}
        return ToolClient.createJsonFail("数据不存在,刷新重试");
      }
      final int rows = storeDao.delById(kid);
      if(rows > 0){
        final ArrayList<String> lists = new ArrayList<>(1);//单文件上传的字段集
        lists.add("thumbnail");
        for(int x = lists.size() - 1; x >= 0; x--){
          asyncService.delFileJsonObject(map.get(lists.get(x)));
        }
        final String[] listMulti = new String[]{"pictures"};//多文件上传的字段集
        for(int x = listMulti.length - 1; x >= 0; x--){
          asyncService.delFileJsonObjects(map.get(listMulti[x]));//多文件上传,json里含json
        }
      }
      return ToolClient.executeRows(rows,"操作成功","删除失败,刷新重试");
    },taskExecutor).join();
  }

  public String delByKeys(final String ids){
    return CompletableFuture.supplyAsync(()->{
      if(ids == null || ids.length() <= 0){
        return ToolClient.jsonValidateField();
      }
      final long[] list = ToolString.keysToArarry(ids);
      if(list == null){
        return ToolClient.createJsonFail("请选择要删除的数据");
      }
      final List<HashMap<String,String>> files = storeDao.queryFiles(list);
      if(files.isEmpty()){// 此处的files == null永远不为true，所以验证非空时 if(!list.isEmpty()){}
        return ToolClient.createJsonFail("数据不存在,刷新重试");
      }
      final int rows = storeDao.delByKeys(list);
      if(rows > 0){
        final ArrayList<String> lists = new ArrayList<>(1);
        lists.add("thumbnail");
        for(int x = lists.size() - 1; x >= 0; x--){
          final String key = lists.get(x);
          for(int y = files.size() - 1; y >= 0; y--){
            final HashMap<String,String> map = files.get(y);
            for(final String k : map.keySet()){
              if(k.equals(key)){
                asyncService.delFileJsonObject(map.get(key));//视情况是否删除时连同删除文件
                break;
              }
            }
          }
        }
        final String[] listMulti = new String[]{"pictures"};//多文件上传的字段集
        for(int x = listMulti.length - 1; x >= 0; x--){
          for(int y = files.size() - 1; y >= 0; y--){
            asyncService.delFileJsonObjects(files.get(y).get(listMulti[x]));//多文件上传,json里含json
          }
        }
      }
      return ToolClient.executeRows(rows,"操作成功","数据不存在,刷新重试");
    },taskExecutor).join();
  }

  public String listData(final PageFormData formData){
    return CompletableFuture.supplyAsync(()->{
      try{
        if(ToolClient.dataTableMysql(formData) == null) return ToolClient.jsonValidateField();
        final CompletableFuture<List<HashMap<String,Object>>> listData = CompletableFuture.supplyAsync(() -> storeDao.getListData(formData),taskExecutor);
        final CompletableFuture<Integer> listTotal = CompletableFuture.supplyAsync(() -> storeDao.getListTotal(formData),taskExecutor);
        CompletableFuture.allOf(listData,listTotal).join();
        return ToolClient.dataTableOK(listData.join(),listTotal.join());
      } catch (final Exception ignored){
        return ToolClient.dataTableException();
      }
    },taskExecutor).join();
  }
}